Let’s start by reading your data:

# Import libraries:
# Load libraries
# Note: commented-out libraries are experimental libraries for other functions not used in this final analysis file

#load some useful libraries
library(limma)
library(edgeR)
library(sns)
library(data.table)
library(tidyr)
library(tidyverse)
library(sjmisc)
require(foreign)
library(foreign)
require(ggplot2)
require(MASS)
require(Hmisc)
require(reshape2)
library(stringr)
library(rlist)
library(rlang)
library(forcats)
library(dplyr)
library(tidyverse)
library(ggh4x)
require(tidyselect)
library(DataCombine)
library(ggrepel)
library(ggbeeswarm)
library(ggsignif)
library(ggpubr)
library(btools)
library(ggpmisc)
library(quantreg)
library(broom)
library(gginnards)
library(broom.mixed)
library(scales)

#Corncob and Phyloseq:
library(corncob)
library(compositions)
Welcome to compositions, a package for compositional data analysis.
Find an intro with "? compositions"


Attaching package: ‘compositions’

The following object is masked from ‘package:SparseM’:

    norm

The following objects are masked from ‘package:stats’:

    anova, cor, cov, dist, var

The following objects are masked from ‘package:base’:

    %*%, norm, scale, scale.default
library(phyloseq)

# Import data:
otus <- read.csv("gut_full.csv", check.names=F)
taxa <- read.csv("taxa.csv",sep='\t')
otus$sex <- factor(otus$sex) #factorize sex
otus$vendor_dashboard <- factor(otus$vendor_dashboard)
otus$bowel <- factor(as.numeric(factor(otus$bowel, levels = c(1,2,3,4), labels = c(1,2,3,4))))
otus <- otus[ which(otus$vendor_dashboard == "Second Genome" | otus$vendor_dashboard == "research-microbiome"),] # keep only data where vendor is explicit
otus$vendor_dashboard = str_replace_all(otus$vendor_dashboard,"research-microbiome","DNA Genotek")
otus$vendor_dashboard <- factor(otus$vendor_dashboard) # factorize vendor
#otus[ which(otus$vendor_dashboard == "Second Genome"),]
otus <- within(otus, bowel <- relevel(bowel, ref = 3))

# Pre-processing and checking validity of data
# Algorithms provided by Christian Diener, PhD:
##############################################################################
dat <- otus
otus <- otus[!duplicated(otus$public_client_id), ]
genus_cols <- grepl("taxa_", names(otus))
rownames(otus) <- otus$public_client_id
sdata <- otus[, !genus_cols]
bowel <- paste0(sdata['bowel'])
table(sdata['bowel'])

   3    1    2    4 
1796   83  769   41 
otus <- as.matrix(otus[, genus_cols])
colnames(otus) <- gsub("taxa_", "", colnames(otus))
tax_matrix <- as.matrix(taxa[, 2:ncol(taxa)])
rownames(tax_matrix) <- taxa[, 1]
as.data.frame(otus)

Now we convert it to fit in a phyloseq object. We need to fulfill the following rules:

  1. The OTU table is a matrix with rows being samples and each column being a taxon.
  2. The taxonomy table must be a matrix with rows being taxa and columns being ranks.
  3. The sample data must be data frame with rows being samples.

To double check if everything works let’s do some validity checks:

stopifnot(all(rownames(otus) %in% rownames(sdata)))
stopifnot(nrow(otus) == nrow(sdata))
print("sample names match")
[1] "sample names match"
stopifnot(all(colnames(otus) %in% rownames(tax_matrix)))
stopifnot(ncol(otus) == nrow(tax_matrix))
stopifnot(!anyDuplicated(tax_matrix))
print("taxa look okay")
[1] "taxa look okay"
stopifnot(!anyDuplicated(sdata))
print("sample data looks okay")
[1] "sample data looks okay"

If that passes we can go ahead and build our phyloseq object.

ps <- phyloseq(
  otu_table(otus, taxa_are_rows = FALSE),
  tax_table(tax_matrix),
  sample_data(sdata)
)

ps
phyloseq-class experiment-level object
otu_table()   OTU Table:         [ 68 taxa and 2689 samples ]
sample_data() Sample Data:       [ 2689 samples by 7 sample variables ]
tax_table()   Taxonomy Table:    [ 68 taxa by 6 taxonomic ranks ]
names(sample_data(ps))
[1] "public_client_id" "sex"              "age"              "BMI_CALC"        
[5] "vendor_dashboard" "bowel"            "eGFR"            
bowel <- sample_data(ps)$bowel

##############################################################################
#Differential Test
#Uncomment this code chunk to run the CORNCOB modeling.
#Otherwise, load the dv_analysis object already saved from a previously completed modeling run.
#dv_analysis <- differentialTest(formula = ~ bowel + sex + age + BMI_CALC + vendor_dashboard + eGFR,
#                                 phi.formula = ~ 1,
#                                 formula_null = ~ sex + age + BMI_CALC + vendor_dashboard + eGFR,
#                                 phi.formula_null = ~ 1,
#                                 data = ps,
#                                 test = "LRT", boot = FALSE,
#                                 full_output = TRUE,
#                                 fdr_cutoff = 0.05)
#Load a previous CORNCOB modeling
#Click on the "corncob.rds" file in the folder with R Studio open and add the dataframe to the environment. Name it "corncob":
dv_analysis <- corncob
#See the significant taxa from the computation:
dv_analysis$significant_taxa
 [1] "Bacteria.Actinobacteria.Actinobacteria.Bifidobacteriales.Bifidobacteriaceae.Bifidobacterium"   
 [2] "Bacteria.Actinobacteria.Coriobacteriia.Coriobacteriales.Coriobacteriaceae.Collinsella"         
 [3] "Bacteria.Actinobacteria.Coriobacteriia.Coriobacteriales.Eggerthellaceae.Adlercreutzia"         
 [4] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Bacteroidaceae.Bacteroides"                   
 [5] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Marinifilaceae.Odoribacter"                   
 [6] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Rikenellaceae.Alistipes"                      
 [7] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Tannerellaceae.Parabacteroides"               
 [8] "Bacteria.Firmicutes.Bacilli.Lactobacillales.Streptococcaceae.Streptococcus"                    
 [9] "Bacteria.Firmicutes.Clostridia.Clostridiales.Christensenellaceae.Christensenellaceae_R-7_group"
[10] "Bacteria.Firmicutes.Clostridia.Clostridiales.Christensenellaceae.nan"                          
[11] "Bacteria.Firmicutes.Clostridia.Clostridiales.Clostridiales_vadinBB60_group.nan"                
[12] "Bacteria.Firmicutes.Clostridia.Clostridiales.Family_XIII.Family_XIII_AD3011_group"             
[13] "Bacteria.Firmicutes.Clostridia.Clostridiales.Family_XIII.Family_XIII_UCG-001"                  
[14] "Bacteria.Firmicutes.Clostridia.Clostridiales.Family_XIII.nan"                                  
[15] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Agathobacter"                     
[16] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Blautia"                          
[17] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnoclostridium"                
[18] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnospira"                      
[19] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnospiraceae_NK4A136_group"    
[20] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnospiraceae_UCG-004"          
[21] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Marvinbryantia"                   
[22] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.nan"                              
[23] "Bacteria.Firmicutes.Clostridia.Clostridiales.Peptostreptococcaceae.Romboutsia"                 
[24] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Anaerotruncus"                    
[25] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Butyricicoccus"                   
[26] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Candidatus_Soleaferrea"           
[27] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.DTU089"                           
[28] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Faecalibacterium"                 
[29] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.GCA-900066225"                    
[30] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Intestinimonas"                   
[31] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Negativibacillus"                 
[32] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Oscillibacter"                    
[33] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminiclostridium_5"              
[34] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminiclostridium_9"              
[35] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_NK4A214_group"    
[36] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-002"          
[37] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-004"          
[38] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-005"          
[39] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-013"          
[40] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcus_1"                   
[41] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcus_2"                   
[42] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Subdoligranulum"                  
[43] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.UBA1819"                          
[44] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.nan"                              
[45] "Bacteria.Firmicutes.Erysipelotrichia.Erysipelotrichales.Erysipelotrichaceae.Holdemania"        
[46] "Bacteria.Firmicutes.Erysipelotrichia.Erysipelotrichales.Erysipelotrichaceae.nan"               
[47] "Bacteria.Verrucomicrobia.Verrucomicrobiae.Verrucomicrobiales.Akkermansiaceae.Akkermansia"      
#prepare the taxa df for manipulation:
taxa<-dv_analysis$all_models
dv_analysis$significant_taxa
 [1] "Bacteria.Actinobacteria.Actinobacteria.Bifidobacteriales.Bifidobacteriaceae.Bifidobacterium"   
 [2] "Bacteria.Actinobacteria.Coriobacteriia.Coriobacteriales.Coriobacteriaceae.Collinsella"         
 [3] "Bacteria.Actinobacteria.Coriobacteriia.Coriobacteriales.Eggerthellaceae.Adlercreutzia"         
 [4] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Bacteroidaceae.Bacteroides"                   
 [5] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Marinifilaceae.Odoribacter"                   
 [6] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Rikenellaceae.Alistipes"                      
 [7] "Bacteria.Bacteroidetes.Bacteroidia.Bacteroidales.Tannerellaceae.Parabacteroides"               
 [8] "Bacteria.Firmicutes.Bacilli.Lactobacillales.Streptococcaceae.Streptococcus"                    
 [9] "Bacteria.Firmicutes.Clostridia.Clostridiales.Christensenellaceae.Christensenellaceae_R-7_group"
[10] "Bacteria.Firmicutes.Clostridia.Clostridiales.Christensenellaceae.nan"                          
[11] "Bacteria.Firmicutes.Clostridia.Clostridiales.Clostridiales_vadinBB60_group.nan"                
[12] "Bacteria.Firmicutes.Clostridia.Clostridiales.Family_XIII.Family_XIII_AD3011_group"             
[13] "Bacteria.Firmicutes.Clostridia.Clostridiales.Family_XIII.Family_XIII_UCG-001"                  
[14] "Bacteria.Firmicutes.Clostridia.Clostridiales.Family_XIII.nan"                                  
[15] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Agathobacter"                     
[16] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Blautia"                          
[17] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnoclostridium"                
[18] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnospira"                      
[19] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnospiraceae_NK4A136_group"    
[20] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Lachnospiraceae_UCG-004"          
[21] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.Marvinbryantia"                   
[22] "Bacteria.Firmicutes.Clostridia.Clostridiales.Lachnospiraceae.nan"                              
[23] "Bacteria.Firmicutes.Clostridia.Clostridiales.Peptostreptococcaceae.Romboutsia"                 
[24] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Anaerotruncus"                    
[25] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Butyricicoccus"                   
[26] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Candidatus_Soleaferrea"           
[27] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.DTU089"                           
[28] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Faecalibacterium"                 
[29] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.GCA-900066225"                    
[30] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Intestinimonas"                   
[31] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Negativibacillus"                 
[32] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Oscillibacter"                    
[33] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminiclostridium_5"              
[34] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminiclostridium_9"              
[35] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_NK4A214_group"    
[36] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-002"          
[37] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-004"          
[38] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-005"          
[39] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcaceae_UCG-013"          
[40] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcus_1"                   
[41] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Ruminococcus_2"                   
[42] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.Subdoligranulum"                  
[43] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.UBA1819"                          
[44] "Bacteria.Firmicutes.Clostridia.Clostridiales.Ruminococcaceae.nan"                              
[45] "Bacteria.Firmicutes.Erysipelotrichia.Erysipelotrichales.Erysipelotrichaceae.Holdemania"        
[46] "Bacteria.Firmicutes.Erysipelotrichia.Erysipelotrichales.Erysipelotrichaceae.nan"               
[47] "Bacteria.Verrucomicrobia.Verrucomicrobiae.Verrucomicrobiales.Akkermansiaceae.Akkermansia"      
as.data.frame(dv_analysis$p_fdr)
taxa_p <- DropNA(as.data.frame(dv_analysis$p_fdr), Var = "dv_analysis$p_fdr")
0 rows dropped from the data frame because of missing values.
taxa_p[1]
[1] 0.02120539
taxa[[1]]$coefficients
                                     Estimate  Std. Error     t value     Pr(>|t|)
mu.(Intercept)                   -3.368074680 0.182186294 -18.4869816 6.486060e-72
mu.bowel1                         0.108766498 0.121122817   0.8979852 3.692741e-01
mu.bowel2                         0.136368966 0.046755183   2.9166599 3.567424e-03
mu.bowel4                        -0.212360465 0.178644229  -1.1887340 2.346497e-01
mu.sexW                          -0.212789194 0.048369795  -4.3992163 1.128862e-05
mu.age                           -0.016148200 0.001821779  -8.8639749 1.378229e-18
mu.BMI_CALC                      -0.003154924 0.003370311  -0.9360928 3.493098e-01
mu.vendor_dashboardSecond Genome  0.127694322 0.060993339   2.0935782 3.639137e-02
mu.eGFR                           0.001582766 0.001243639   1.2726892 2.032388e-01
phi.(Intercept)                  -2.808912916 0.043294681 -64.8789385 0.000000e+00
#Load the arivale_phylo.rds file in the project folder and load the object into the environment.

#Rarefy the genotek dataset to an even depth using phyloseq.
sample_data(arivale_phylo) 
Sample Data:        [3653 samples by 26 sample variables]:
#Tom Wilmanski, PhD's code:
########################################################################################
rarefied_genotek=rarefy_even_depth(arivale_phylo, sample.size = min(sample_sums(arivale_phylo)),
  rngseed = 111, replace = FALSE, trimOTUs = TRUE, verbose = TRUE)
`set.seed(111)` was used to initialize repeatable random subsampling.
Please record this for your records so others can reproduce.
Try `set.seed(111); .Random.seed` for the full vector
...
25984OTUs were removed because they are no longer 
present in any sample after random subsampling

...
richness <- estimate_richness(rarefied_genotek, measures=c("Shannon","Observed"))

saveRDS(richness, "richness.rds")
########################################################################################

richness$public_client_id <-sample_data(rarefied_genotek)$public_client_id
library(btools)
richness$Pielou <- richness$Shannon/richness$Observed

richness
hist(richness$Pielou,
     main = "Pielou's Evenness (Shannon/Observed ASV)",
     xlab = "Evenness",
     xlim = c(0,0.05),
     breaks = 200)


hist(richness$Shannon,
     main = "Shannon Diversity",
     xlab = "Diversity Index",
     xlim = c(0,6),
     breaks = 20)


hist(richness$Observed,
     main = "Observed ASVs",
     xlab = "ASVs",
     xlim = c(0,1000),
     breaks = 30)

combinations <- list(c("Constipation","Low Normal"),
                                 c("Constipation","High Normal"),
                                 c("Constipation","Diarrhea"),
                                 c("Low Normal","High Normal"),
                                 c("Low Normal","Diarrhea"),
                                 c("High Normal","Diarrhea"))
dat$bowel <- factor(dat$bowel, levels = c("Constipation", "Low Normal", "High Normal", "Diarrhea"), labels = c("Constipation", "Low Normal", "High Normal", "Diarrhea"))
#Begin preparing gut microbiome data results for plotting
#Import gut df for preprocessing:

df <- read.csv("gut_full.csv", check.names=F)
colnames(df) = gsub("nan", "Unclassified", colnames(df))
comparisons = list(c("Constipation","High Normal"),c("Low Normal","High Normal"),c("Diarrhea","High Normal"))
df$bowel <- factor(df$bowel, levels = c(1,2,3,4), labels = c("Constipation", "Low Normal", "High Normal", "Diarrhea"))
df_otus <- dplyr::select(df, -c("public_client_id","bowel","vendor_dashboard","sex","age","BMI_CALC","eGFR"))

df_otus <- as.data.frame(clr(as.matrix(df_otus)))
df_select <- dplyr::select(df, c(1:7))
df_otus <- cbind(df_select,df_otus)
df <- df_otus
dat <- df_otus

sam.n <- function(x){return(c(y = mean(x), label = length(x)))}

# ggplot2 plots
library(gplots)

Attaching package: ‘gplots’

The following object is masked from ‘package:stats’:

    lowess
library(ggrepel)
library(ggbreak)
ggbreak v0.1.0

If you use ggbreak in published research, please cite the following paper:

S Xu, M Chen, T Feng, L Zhan, L Zhou, G Yu. Use ggbreak to effectively
utilize plotting space to deal with large datasets and outliers. Frontiers in
Genetics. 2021, 12:774846. doi: 10.3389/fgene.2021.774846 
library(sommer)
Loading required package: Matrix

Attaching package: ‘Matrix’

The following objects are masked from ‘package:tidyr’:

    expand, pack, unpack

Loading required package: crayon

Attaching package: ‘crayon’

The following object is masked from ‘package:rlang’:

    chr

The following object is masked from ‘package:ggplot2’:

    %+%

[]==================================================================[]
[]   Solving Mixed Model Equations in R (sommer) 4.1.8 (2022-09-01) []
[]   ------------- Multivariate Linear Mixed Models --------------  []
[]   Author: Giovanny Covarrubias-Pazaran                           []
[]   Published: PLoS ONE 2016, 11(6):1-15                           []
[]   Dedicated to the University of Chapingo and UW-Madison         []
[]   Type 'vignette('v1.sommer.quick.start')' for a short tutorial  []
[]   Type 'citation('sommer')' to know how to cite sommer           []
[]==================================================================[]
sommer is updated on CRAN every 4-months due to CRAN policies
Newest source is available at https://github.com/covaruber/sommer
To install type: library(devtools); install_github('covaruber/sommer')
# Create the dfs to store BMF metadata and p values for each hit
const <- c()
const_p <- c()
low <- c()
low_p <- c()
diarrhea <- c()
diarrhea_p <- c()
taxa_names <- c()
family_names <- c()
genus_names <- c()
likelihood <- c()
adj_p <- c()
names(dv_analysis$p) = gsub("nan", "Unclassified", names(dv_analysis$p))

#Add all the p values and metadata to the right dfs:
for (i in 1:length(dv_analysis$all_models[names(dv_analysis$p)])) {
  const_p[i] <- dv_analysis$all_models[[i]]$coefficients[2,4]
  const[i] <- dv_analysis$all_models[[i]]$coefficients[2,1]
  low_p[i] <- dv_analysis$all_models[[i]]$coefficients[3,4]
  low[i] <- dv_analysis$all_models[[i]]$coefficients[3,1]
  diarrhea_p[i] <- dv_analysis$all_models[[i]]$coefficients[4,4]
  diarrhea[i] <- dv_analysis$all_models[[i]]$coefficients[4,1]
  taxa_names[i] <- names(dv_analysis$p)[i]
  family_names[i] <- strsplit(taxa_names[i],'.',fixed=TRUE)[[1]][5]
  genus_names[i] <- strsplit(taxa_names[i],'.',fixed=TRUE)[[1]][6]
  likelihood[i] <- dv_analysis$all_models[[i]]$logL
  adj_p[i] <- dv_analysis$p_fdr[[i]]
}
genus_names[i] <- strsplit(taxa_names[i],'.',fixed=TRUE)[[1]][6]

#Create final p-value df:
p_df <- bind_cols(taxa_names,family_names,genus_names, likelihood, adj_p, const,const_p,low,low_p,diarrhea,diarrhea_p)
New names:
• `` -> `...1`
• `` -> `...2`
• `` -> `...3`
• `` -> `...4`
• `` -> `...5`
• `` -> `...6`
• `` -> `...7`
• `` -> `...8`
• `` -> `...9`
• `` -> `...10`
• `` -> `...11`
names(p_df) <- c("Genera","Family","Genus","LogL","Adj.P","Const.Beta","Const.P.Val","Low.Beta","Low.P.Val","Diarrhea.Beta","Diarrhea.P.Val")
p_df$Combined <- paste(p_df$Family,p_df$Genus)
ab <- colSums(df_otus[names(df_otus) %in% paste("taxa_",names(dv_analysis$p),sep="")])/colSums(!!df_otus[names(df_otus) %in% paste("taxa_",names(dv_analysis$p),sep="")])
p_df$Mean.Abundance <- ab[paste("taxa_",p_df$Genera,sep="")]
p_df$Const.Adj.P.Val <- p.adjust(const_p, method = "fdr", n = length(const_p))
p_df$Low.Adj.P.Val <- p.adjust(low_p, method = "fdr", n = length(low_p))
p_df$Diarrhea.Adj.P.Val <- p.adjust(diarrhea_p, method = "fdr", n = length(diarrhea_p))
p_df <- p_df[order(-p_df$Mean.Abundance),]
set <- subset(p_df[which(p_df$Adj.P < 0.05),], Genus != 'Unclassified')
set <- subset(set[order(-set$Mean.Abundance),], Genus != 'Unclassified')
abundant_list <- list()
abundant_genus <- list()
abundant <- paste("taxa_",set[order(-set$Mean.Abundance),]$Genera,sep="")
for (i in 1:68) {
  abundant_list[i] <- paste(strsplit(abundant[i],'.',fixed=TRUE)[[1]][5],strsplit(abundant[i],'.',fixed=TRUE)[[1]][6])
  abundant_genus[i] <- paste(strsplit(abundant[i],'.',fixed=TRUE)[[1]][6])
}

#top 10 most abundant non-unclassified hits
abundant_trunc <- set[match(abundant_list[!is.na(set$Combined[match(abundant_list,set$Combined)])],set$Combined),][which(set$Adj.P<0.05),]$Combined[1:10]
`%!in%` <- Negate(`%in%`)
t <- set[set$Combined %!in% abundant_trunc,]

#create the set of hits that are top 10 most abundant, Akkermansia, and top 9 most significant = 20 hits:
span <- rbind(set[order(set[-order(set[!set$Combined %in% abundant_trunc,]$Adj.P),][which(set$Adj.P<0.05),]$Mean.Abundance %!in% abundant_trunc),][1:10,],
t[match('Akkermansiaceae Akkermansia',t$Combined),],
t[order(t$Const.Adj.P.Val),][1:9,])
span$Letters <- LETTERS[1:20]
p_df$Letters <- c(NA)
test <- rbind(span,p_df[p_df$Combined %!in% span$Combined,])
test <- test[!duplicated(test$Genera),]
p_df <- test
p_df <- p_df[order(p_df$Adj.P),]
p_df <- p_df[order(-p_df$Mean.Abundance),]
#Pielou's Evenness:
model = y ~ x
df_num <- merge(richness, df_otus, by="public_client_id")
df_num$bowel <- factor(df_num$bowel, order = TRUE)
d1_plot <- lm(Pielou ~ bowel, data = df_num)
pval1 = summary(d1_plot)$coefficients[2,4]
r1 = summary(d1_plot)$adj.r.squared
pval1
[1] 0.01814568
r1
[1] 0.01204487
d1 <- ggplot(data = df_num, aes(x = factor(bowel, level = c("Constipation", "Low Normal", "High Normal", "Diarrhea"), labels = c("Constipation", "Low Normal", "High Normal", "Diarrhea")), y = Pielou, group = factor(bowel))) +
  scale_x_discrete(bquote(atop(~italic("adj R")^2~" = "~.(formatC(as.numeric(r1),3)),~italic("P value")~" = "~.(formatC(as.numeric(pval1),3)))))+
  geom_beeswarm(aes(color = bowel), cex = 0.5) +
  geom_boxplot(alpha=0) +
  ylim(0.005,0.05)+
  geom_smooth(method = "lm", formula = y ~ x, aes(group = 1)) +
  ggtitle(label = "C)\nPielou's Evenness vs BMF") +
  xlab("Bowel Movement Frequency (BMF)") +
  ylab("Pielou's Evenness") +
  scale_colour_discrete(name="BMF Category", limits = c("Constipation", "Low Normal", "High Normal", "Diarrhea"), labels=c("Constipation", "Low Normal", "High Normal", "Diarrhea")) +
  guides(colour = guide_legend(override.aes = list(size=7))) +
  theme(plot.title = element_text(size=10), legend.text = element_text(size = 10), legend.title = element_text(size = 10), axis.text.x = element_blank(), axis.title.y = element_text(size = 10))
d1
Warning: Removed 1 rows containing non-finite values (stat_boxplot).
Warning: Removed 1 rows containing non-finite values (stat_smooth).
Warning: Removed 1 rows containing missing values (position_beeswarm).

#Shannon Diversity:
model = y ~ x
d2_plot <- lm(Shannon ~ bowel, data = df_num)
pval2 = summary(d2_plot)$coefficients[2,4]
r2 = summary(d2_plot)$adj.r.squared
pval2
[1] 0.005892245
r2
[1] 0.01384
d2 <- ggplot(data = df_num, aes(x = factor(bowel, level = c("Constipation", "Low Normal", "High Normal", "Diarrhea"), labels = c("Constipation", "Low Normal", "High Normal", "Diarrhea")), y = Shannon, group = bowel)) +
  scale_x_discrete(bquote(atop(~italic("adj R")^2~" = "~.(formatC(as.numeric(r2),3)),~italic("P value")~" = "~.(formatC(as.numeric(pval2),3)))))+
  geom_beeswarm(aes(color = factor(bowel)), cex = 0.5) +
  geom_boxplot(alpha=0) +
  geom_smooth(method = "lm", formula = y ~ x, aes(group = 1)) +
  ggtitle(label = "B)\nShannon Diversity vs BMF") +
  xlab("Bowel Movement Frequency (BMF)") +
  ylab("Shannon Diversity") +
  scale_colour_discrete(name="BMF Category", limits = c("Constipation", "Low Normal", "High Normal", "Diarrhea"), labels=c("Constipation", "Low Normal", "High Normal", "Diarrhea")) +
  guides(colour = guide_legend(override.aes = list(size=7))) +
  theme(plot.title = element_text(size=10), legend.text = element_text(size = 10), legend.title = element_text(size = 10), axis.text.x = element_blank(), axis.title.y = element_text(size = 10))
d2


#Observed ASVs:
model = y ~ x
d3_plot <- lm(Observed ~ bowel, data = df_num)
pval3 = summary(d3_plot)$coefficients[2,4]
r3 = summary(d3_plot)$adj.r.squared
pval3
[1] 0.0009015642
r3
[1] 0.0208449
d3 <- ggplot(data = df_num, aes(x = factor(bowel, level = c("Constipation", "Low Normal", "High Normal", "Diarrhea"), labels = c("Constipation", "Low Normal", "High Normal", "Diarrhea")), y = Observed, group = bowel))+
  scale_x_discrete(bquote(atop(~italic("adj R")^2~" = "~.(formatC(as.numeric(r3),3)),~italic("P value")~" = "~.(formatC(as.numeric(pval3),3)))))+
  geom_beeswarm(aes(color = factor(bowel)), cex = 0.5) +
  geom_boxplot(alpha=0) +
  geom_smooth(method = "lm", formula = y ~ x, aes(group = 1)) +
  ggtitle(label = "A)\nObserved ASVs vs BMF") +
  xlab("Bowel Movement Frequency (BMF)") +
  ylab("Observed ASVs") +
  scale_colour_discrete(name="BMF Category", limits = c("Constipation", "Low Normal", "High Normal", "Diarrhea"), labels=c("Constipation", "Low Normal", "High Normal", "Diarrhea")) +
  guides(colour = guide_legend(override.aes = list(size=7))) +
  theme(plot.title = element_text(size=10), legend.text = element_text(size = 10), legend.title = element_text(size = 10), axis.text.x = element_blank(), axis.title.y = element_text(size = 10))
d3


PSO <- ggarrange(d3, d2, d1, legend = "top", align = "hv", common.legend = TRUE, widths = c(7,7,7), heights = c(20,20,20), nrow = 1, ncol = 3)+ theme(plot.margin = margin(0,0,0,0))
Warning: Removed 1 rows containing non-finite values (stat_boxplot).
Warning: Removed 1 rows containing non-finite values (stat_smooth).
Warning: Removed 1 rows containing missing values (position_beeswarm).
PSO
ggsave(
  "PSOvBMF.png",
  plot = PSO,
  device = NULL,
  path = NULL,
  scale = 1,
  width = NA,
  height = NA,
  units = c("in", "cm", "mm", "px"),
  dpi = 300,
  limitsize = TRUE,
  bg = NULL
)
Saving 6.86 x 4.24 in image

#Annotation function:
sig = function(x){
  if(x < 0.001){"***"} 
  else if(x < 0.01){"**"}
  else if(x < 0.05){"*"}
  else{NA}}

#use gut df to construct column-specific df for plotting function
df <- read.csv("gut_full.csv", check.names=F)
colnames(df) = gsub("nan", "Unclassified", colnames(df))
comparisons = list(c("Constipation","High Normal"),c("Low Normal","High Normal"),c("Diarrhea","High Normal"))
df$bowel <- factor(df$bowel, levels = c(1,2,3,4), labels = c("Constipation", "Low Normal", "High Normal", "Diarrhea"))
df_otus <- dplyr::select(df, -c("public_client_id","bowel","vendor_dashboard","sex","age","BMI_CALC","eGFR"))

#refresh dataframes:
df_otus <- as.data.frame(clr(as.matrix(df_otus)))
df_select <- dplyr::select(df, c(1:7))
df_otus <- cbind(df_select,df_otus)
df <- df_otus
dat <- df_otus

#Initialize vectors:
df$p.value <- NA
df$pval <- NULL
df$p.val <- NULL
counter <<- 1

#Plotting:

# Special Graphing Function:
########################################
test = function(x,y,z,j) {
  work <- NULL
  results <- NULL
  x = NULL
  y = NULL
  if (counter == 1) {z = comparisons[[1]][1]}
  else if (counter == 2) {z = comparisons[[2]][1]}
  else if (counter > 2) {z = comparisons[[3]][1]}
  temp <- data.frame("name" = NA, "p.value" = NA, "bowel" = NA)
  for (i in 1:20) {
    temp$name <- paste("genus_",span$Genera[[i]],sep="")
    temp$p.value <- span$Const.Adj.P.Val[[i]] 
    temp$bowel <- "Constipation"
    work <- rbind(work,temp)
    temp$p.value <- span$Low.Adj.P.Val[[i]] 
    temp$bowel <- "Low Normal"
    work <- rbind(work,temp)
    temp$p.value <- span$Diarrhea.Adj.P.Val[[i]] 
    temp$bowel <- "Diarrhea"
    work <- rbind(work,temp)
  }
  if (z[[1]][1] == comparisons[[1]][1]) {results <- list(p.value = work$p.value[3*(j-1)+1])}
  else if (z[[1]][1] == comparisons[[2]][1]) {results <- list(p.value = work$p.value[3*(j-1)+1+1]) }
  else if (z[[1]][1] == comparisons[[3]][1]) {results <- list(p.value = work$p.value[3*(j-1)+1+2])}
  counter<<-counter+1
  if (counter > 3) {counter<<-1}
  return(results)
}
########################################

#Store plots in list of plots for looping to plot next:
myplots <- list()  # new empty list
df_test <- df
df_test[df_test==0] <- NA
for (genera in 1:20) {
  y_name <- paste("taxa_",span$Genera[genera],sep="")
  myplots[[genera]] <- local({
    plotlim_lower = min(
df_test[!is.na(df_test[y_name]),][y_name])
    plotlim_upper = max(
df_test[!is.na(df_test[y_name]),][y_name])
    plotlim_bar = plotlim_lower - 4
    plotlim_margin = 6
    genera <- genera
    plt <- ggplot(data = df_test, aes(x = bowel, y = .data[[y_name]], group = bowel)) +
    scale_x_discrete(guide = guide_axis(n.dodge = 2))+
    geom_jitter(aes(color = bowel),  size = 0.1, cex = 0.05) +
    geom_boxplot(data = df_test, alpha=0.0,outlier.shape = NA) +
    theme(text = element_text(size = 9)) +
    ggtitle(label = paste(span$Family[genera],"\n",span$Genus[genera],sep="")) +
    geom_signif(data = df_test, comparisons = comparisons, map_signif_level = sig, test = 'test', test.args = list(z = comparisons, j = genera), y_position = plotlim_bar,step_increase = 0.15,  size = 0.5, 
                textsize = 1.5,
                tip_length = c(0,0)) +
    coord_cartesian(ylim=c(plotlim_lower,plotlim_upper),clip="off")+
    labs(color = "BMF Category", y = ifelse((genera == 1 | genera  == 6 | genera  == 11 | genera == 16),"CLR Abundance","")) +
    guides(colour = guide_legend(override.aes = list(size=7), title.position = 'left', nrow = 1, ncol = 4)) +
    theme(plot.margin = unit(c(0,0,plotlim_margin,0), "cm"), 
          plot.title = element_text(size=5.75), 
          legend.title = element_text(size=10), 
          plot.subtitle = element_text(size=10), 
          legend.text = element_text(size=7),
          axis.text.x = element_blank(), 
          axis.text.y = element_text(size=7), 
          axis.title.y = element_text(size=7),
          axis.title.x = element_blank(),
          aspect.ratio = 0.95)
  })
}
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
Warning: Duplicated aesthetics after name standardisation: size
#Truncate to the top 20 including Akkermansia, most abundant, and most significant:
title <- list()
for(i in seq(1:20)) { title[i] <- myplots[[c(i)]]$labels$title }
plots1 <- myplots[title %in% paste(
  span$Family,
  "\n",
  span$Genus,sep="")][1:20]
plots_final <- plots1[!sapply(plots1,is.null)]

#Arrange the plots:
final1 <- ggarrange(plotlist = plots_final[1:5], labels = LETTERS[1:5], legend = "top", align = "hv", font.label = list(size = 8), common.legend = TRUE, nrow = 1, ncol = 5) + theme(plot.margin = unit(c(0,0,0,0), "cm"))
Warning: Removed 3 rows containing non-finite values (stat_boxplot).
Warning: Removed 3 rows containing non-finite values (stat_signif).
Warning: Removed 3 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 3 rows containing non-finite values (stat_boxplot).
Warning: Removed 3 rows containing non-finite values (stat_signif).
Warning: Removed 3 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 56 rows containing non-finite values (stat_boxplot).
Warning: Removed 56 rows containing non-finite values (stat_signif).
Warning: Removed 56 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 2 rows containing non-finite values (stat_boxplot).
Warning: Removed 2 rows containing non-finite values (stat_signif).
Warning: Removed 2 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 85 rows containing non-finite values (stat_boxplot).
Warning: Removed 85 rows containing non-finite values (stat_signif).
Warning: Removed 85 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 171 rows containing non-finite values (stat_boxplot).
Warning: Removed 171 rows containing non-finite values (stat_signif).
Warning: Removed 171 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
final1

final2 <- ggarrange(plotlist = plots_final[6:10], labels = LETTERS[6:10], legend = "top", align = "hv", font.label = list(size = 8), common.legend = TRUE, nrow = 1, ncol = 5) + theme(plot.margin = unit(c(0,0,0,0), "cm"))
Warning: Removed 113 rows containing non-finite values (stat_boxplot).
Warning: Removed 113 rows containing non-finite values (stat_signif).
Warning: Removed 113 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 113 rows containing non-finite values (stat_boxplot).
Warning: Removed 113 rows containing non-finite values (stat_signif).
Warning: Removed 113 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 98 rows containing non-finite values (stat_boxplot).
Warning: Removed 98 rows containing non-finite values (stat_signif).
Warning: Removed 98 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 607 rows containing non-finite values (stat_boxplot).
Warning: Removed 607 rows containing non-finite values (stat_signif).
Warning: Removed 607 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 171 rows containing non-finite values (stat_boxplot).
Warning: Removed 171 rows containing non-finite values (stat_signif).
Warning: Removed 171 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 4 rows containing non-finite values (stat_boxplot).
Warning: Removed 4 rows containing non-finite values (stat_signif).
Warning: Removed 4 rows containing missing values (geom_point).
Warning: Removed 7 rows containing missing values (geom_signif).
final2


final3 <- ggarrange(plotlist = plots_final[11:15], labels = LETTERS[11:15], legend = "top", align = "hv", font.label = list(size = 8), common.legend = TRUE, nrow = 1, ncol = 5) + theme(plot.margin = unit(c(0,0,0,0), "cm"))
Warning: Removed 762 rows containing non-finite values (stat_boxplot).
Warning: Removed 762 rows containing non-finite values (stat_signif).
Warning: Removed 762 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 762 rows containing non-finite values (stat_boxplot).
Warning: Removed 762 rows containing non-finite values (stat_signif).
Warning: Removed 762 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 271 rows containing non-finite values (stat_boxplot).
Warning: Removed 271 rows containing non-finite values (stat_signif).
Warning: Removed 271 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 591 rows containing non-finite values (stat_boxplot).
Warning: Removed 591 rows containing non-finite values (stat_signif).
Warning: Removed 591 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 147 rows containing non-finite values (stat_boxplot).
Warning: Removed 147 rows containing non-finite values (stat_signif).
Warning: Removed 147 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 240 rows containing non-finite values (stat_boxplot).
Warning: Removed 240 rows containing non-finite values (stat_signif).
Warning: Removed 240 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
final3

final4 <- ggarrange(plotlist = plots_final[16:20], labels = LETTERS[16:20], legend = "top", align = "hv", font.label = list(size = 8), common.legend = TRUE, nrow = 1, ncol = 5) + theme(plot.margin = unit(c(0,0,0,0), "cm"))
Warning: Removed 592 rows containing non-finite values (stat_boxplot).
Warning: Removed 592 rows containing non-finite values (stat_signif).
Warning: Removed 592 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 592 rows containing non-finite values (stat_boxplot).
Warning: Removed 592 rows containing non-finite values (stat_signif).
Warning: Removed 592 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 40 rows containing non-finite values (stat_boxplot).
Warning: Removed 40 rows containing non-finite values (stat_signif).
Warning: Removed 40 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 331 rows containing non-finite values (stat_boxplot).
Warning: Removed 331 rows containing non-finite values (stat_signif).
Warning: Removed 331 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 680 rows containing non-finite values (stat_boxplot).
Warning: Removed 680 rows containing non-finite values (stat_signif).
Warning: Removed 680 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 20 rows containing non-finite values (stat_boxplot).
Warning: Removed 20 rows containing non-finite values (stat_signif).
Warning: Removed 20 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
final4

final_main <- ggarrange(plotlist = plots_final[1:20], labels = LETTERS[1:20], legend = "top", align = "hv", common.legend = TRUE, nrow = 4, ncol = 5)
Warning: Removed 3 rows containing non-finite values (stat_boxplot).
Warning: Removed 3 rows containing non-finite values (stat_signif).
Warning: Removed 3 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 3 rows containing non-finite values (stat_boxplot).
Warning: Removed 3 rows containing non-finite values (stat_signif).
Warning: Removed 3 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 56 rows containing non-finite values (stat_boxplot).
Warning: Removed 56 rows containing non-finite values (stat_signif).
Warning: Removed 56 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 2 rows containing non-finite values (stat_boxplot).
Warning: Removed 2 rows containing non-finite values (stat_signif).
Warning: Removed 2 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 85 rows containing non-finite values (stat_boxplot).
Warning: Removed 85 rows containing non-finite values (stat_signif).
Warning: Removed 85 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 171 rows containing non-finite values (stat_boxplot).
Warning: Removed 171 rows containing non-finite values (stat_signif).
Warning: Removed 171 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 113 rows containing non-finite values (stat_boxplot).
Warning: Removed 113 rows containing non-finite values (stat_signif).
Warning: Removed 113 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 98 rows containing non-finite values (stat_boxplot).
Warning: Removed 98 rows containing non-finite values (stat_signif).
Warning: Removed 98 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 607 rows containing non-finite values (stat_boxplot).
Warning: Removed 607 rows containing non-finite values (stat_signif).
Warning: Removed 607 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 171 rows containing non-finite values (stat_boxplot).
Warning: Removed 171 rows containing non-finite values (stat_signif).
Warning: Removed 171 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 4 rows containing non-finite values (stat_boxplot).
Warning: Removed 4 rows containing non-finite values (stat_signif).
Warning: Removed 4 rows containing missing values (geom_point).
Warning: Removed 7 rows containing missing values (geom_signif).
Warning: Removed 762 rows containing non-finite values (stat_boxplot).
Warning: Removed 762 rows containing non-finite values (stat_signif).
Warning: Removed 762 rows containing missing values (geom_point).
Warning: Removed 8 rows containing missing values (geom_signif).
Warning: Removed 271 rows containing non-finite values (stat_boxplot).
Warning: Removed 271 rows containing non-finite values (stat_signif).
Warning: Removed 271 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 591 rows containing non-finite values (stat_boxplot).
Warning: Removed 591 rows containing non-finite values (stat_signif).
Warning: Removed 591 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 147 rows containing non-finite values (stat_boxplot).
Warning: Removed 147 rows containing non-finite values (stat_signif).
Warning: Removed 147 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 240 rows containing non-finite values (stat_boxplot).
Warning: Removed 240 rows containing non-finite values (stat_signif).
Warning: Removed 240 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 592 rows containing non-finite values (stat_boxplot).
Warning: Removed 592 rows containing non-finite values (stat_signif).
Warning: Removed 592 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 40 rows containing non-finite values (stat_boxplot).
Warning: Removed 40 rows containing non-finite values (stat_signif).
Warning: Removed 40 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 331 rows containing non-finite values (stat_boxplot).
Warning: Removed 331 rows containing non-finite values (stat_signif).
Warning: Removed 331 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 680 rows containing non-finite values (stat_boxplot).
Warning: Removed 680 rows containing non-finite values (stat_signif).
Warning: Removed 680 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
Warning: Removed 20 rows containing non-finite values (stat_boxplot).
Warning: Removed 20 rows containing non-finite values (stat_signif).
Warning: Removed 20 rows containing missing values (geom_point).
Warning: Removed 5 rows containing missing values (geom_signif).
ggsave(
  "BMFvsGenera1.png",
  plot = final1,
  device = NULL,
  path = NULL,
  scale = 1.5,
  width = NA,
  height = NA,
  units = c("in", "cm", "mm", "px"),
  dpi = 300,
  limitsize = TRUE,
  bg = NULL
)
Saving 10.3 x 6.36 in image
ggsave(
  "BMFvsGenera2.png",
  plot = final2,
  device = NULL,
  path = NULL,
  scale = 1.5,
  width = NA,
  height = NA,
  units = c("in", "cm", "mm", "px"),
  dpi = 300,
  limitsize = TRUE,
  bg = NULL
)
Saving 10.3 x 6.36 in image
ggsave(
  "BMFvsGenera3.png",
  plot = final3,
  device = NULL,
  path = NULL,
  scale = 1.5,
  width = NA,
  height = NA,
  units = c("in", "cm", "mm", "px"),
  dpi = 300,
  limitsize = TRUE,
  bg = NULL
)
Saving 10.3 x 6.36 in image
ggsave(
  "BMFvsGenera4.png",
  plot = final4,
  device = NULL,
  path = NULL,
  scale = 1.5,
  width = NA,
  height = NA,
  units = c("in", "cm", "mm", "px"),
  dpi = 300,
  limitsize = TRUE,
  bg = NULL
)
Saving 10.3 x 6.36 in image

LS0tCnRpdGxlOiAiQVNWIEd1dCBNaWNyb2Jpb21lIENPUk5DT0IgUmVncmVzc2lvbiAtIEphbWVzIEpvaG5zb24gLSB2My03LTIzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMZXQncyBzdGFydCBieSByZWFkaW5nIHlvdXIgZGF0YToKCmBgYHtyfQojIEltcG9ydCBsaWJyYXJpZXM6CiMgTG9hZCBsaWJyYXJpZXMKIyBOb3RlOiBjb21tZW50ZWQtb3V0IGxpYnJhcmllcyBhcmUgZXhwZXJpbWVudGFsIGxpYnJhcmllcyBmb3Igb3RoZXIgZnVuY3Rpb25zIG5vdCB1c2VkIGluIHRoaXMgZmluYWwgYW5hbHlzaXMgZmlsZQoKI2xvYWQgc29tZSB1c2VmdWwgbGlicmFyaWVzCmxpYnJhcnkobGltbWEpCmxpYnJhcnkoZWRnZVIpCmxpYnJhcnkoc25zKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNqbWlzYykKcmVxdWlyZShmb3JlaWduKQpsaWJyYXJ5KGZvcmVpZ24pCnJlcXVpcmUoZ2dwbG90MikKcmVxdWlyZShNQVNTKQpyZXF1aXJlKEhtaXNjKQpyZXF1aXJlKHJlc2hhcGUyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkocmxpc3QpCmxpYnJhcnkocmxhbmcpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2doNHgpCnJlcXVpcmUodGlkeXNlbGVjdCkKbGlicmFyeShEYXRhQ29tYmluZSkKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KGdnYmVlc3dhcm0pCmxpYnJhcnkoZ2dzaWduaWYpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KGJ0b29scykKbGlicmFyeShnZ3BtaXNjKQpsaWJyYXJ5KHF1YW50cmVnKQpsaWJyYXJ5KGJyb29tKQpsaWJyYXJ5KGdnaW5uYXJkcykKbGlicmFyeShicm9vbS5taXhlZCkKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoc29tbWVyKQpsaWJyYXJ5KGdwbG90cykKbGlicmFyeShnZ2JyZWFrKQpsaWJyYXJ5KGdncmVwZWwpCgojQ29ybmNvYiBhbmQgUGh5bG9zZXE6CmxpYnJhcnkoY29ybmNvYikKbGlicmFyeShjb21wb3NpdGlvbnMpCmxpYnJhcnkocGh5bG9zZXEpCgojIEltcG9ydCBkYXRhOgpvdHVzIDwtIHJlYWQuY3N2KCJndXRfZnVsbC5jc3YiLCBjaGVjay5uYW1lcz1GKQp0YXhhIDwtIHJlYWQuY3N2KCJ0YXhhLmNzdiIsc2VwPSdcdCcpCm90dXMkc2V4IDwtIGZhY3RvcihvdHVzJHNleCkgI2ZhY3Rvcml6ZSBzZXgKb3R1cyR2ZW5kb3JfZGFzaGJvYXJkIDwtIGZhY3RvcihvdHVzJHZlbmRvcl9kYXNoYm9hcmQpCm90dXMkYm93ZWwgPC0gZmFjdG9yKGFzLm51bWVyaWMoZmFjdG9yKG90dXMkYm93ZWwsIGxldmVscyA9IGMoMSwyLDMsNCksIGxhYmVscyA9IGMoMSwyLDMsNCkpKSkKb3R1cyA8LSBvdHVzWyB3aGljaChvdHVzJHZlbmRvcl9kYXNoYm9hcmQgPT0gIlNlY29uZCBHZW5vbWUiIHwgb3R1cyR2ZW5kb3JfZGFzaGJvYXJkID09ICJyZXNlYXJjaC1taWNyb2Jpb21lIiksXSAjIGtlZXAgb25seSBkYXRhIHdoZXJlIHZlbmRvciBpcyBleHBsaWNpdApvdHVzJHZlbmRvcl9kYXNoYm9hcmQgPSBzdHJfcmVwbGFjZV9hbGwob3R1cyR2ZW5kb3JfZGFzaGJvYXJkLCJyZXNlYXJjaC1taWNyb2Jpb21lIiwiRE5BIEdlbm90ZWsiKQpvdHVzJHZlbmRvcl9kYXNoYm9hcmQgPC0gZmFjdG9yKG90dXMkdmVuZG9yX2Rhc2hib2FyZCkgIyBmYWN0b3JpemUgdmVuZG9yCiNvdHVzWyB3aGljaChvdHVzJHZlbmRvcl9kYXNoYm9hcmQgPT0gIlNlY29uZCBHZW5vbWUiKSxdCm90dXMgPC0gd2l0aGluKG90dXMsIGJvd2VsIDwtIHJlbGV2ZWwoYm93ZWwsIHJlZiA9IDMpKQoKIyBQcmUtcHJvY2Vzc2luZyBhbmQgY2hlY2tpbmcgdmFsaWRpdHkgb2YgZGF0YQojIEFsZ29yaXRobXMgcHJvdmlkZWQgYnkgQ2hyaXN0aWFuIERpZW5lciwgUGhEOgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZGF0IDwtIG90dXMKb3R1cyA8LSBvdHVzWyFkdXBsaWNhdGVkKG90dXMkcHVibGljX2NsaWVudF9pZCksIF0KZ2VudXNfY29scyA8LSBncmVwbCgidGF4YV8iLCBuYW1lcyhvdHVzKSkKcm93bmFtZXMob3R1cykgPC0gb3R1cyRwdWJsaWNfY2xpZW50X2lkCnNkYXRhIDwtIG90dXNbLCAhZ2VudXNfY29sc10KYm93ZWwgPC0gcGFzdGUwKHNkYXRhWydib3dlbCddKQp0YWJsZShzZGF0YVsnYm93ZWwnXSkKb3R1cyA8LSBhcy5tYXRyaXgob3R1c1ssIGdlbnVzX2NvbHNdKQpjb2xuYW1lcyhvdHVzKSA8LSBnc3ViKCJ0YXhhXyIsICIiLCBjb2xuYW1lcyhvdHVzKSkKdGF4X21hdHJpeCA8LSBhcy5tYXRyaXgodGF4YVssIDI6bmNvbCh0YXhhKV0pCnJvd25hbWVzKHRheF9tYXRyaXgpIDwtIHRheGFbLCAxXQphcy5kYXRhLmZyYW1lKG90dXMpCmBgYAoKCk5vdyB3ZSBjb252ZXJ0IGl0IHRvIGZpdCBpbiBhIHBoeWxvc2VxIG9iamVjdC4gV2UgbmVlZCB0byBmdWxmaWxsIHRoZSBmb2xsb3dpbmcgcnVsZXM6CgoxLiBUaGUgT1RVIHRhYmxlIGlzIGEgbWF0cml4IHdpdGggcm93cyBiZWluZyBzYW1wbGVzIGFuZCBlYWNoIGNvbHVtbiBiZWluZyBhIHRheG9uLgoyLiBUaGUgdGF4b25vbXkgdGFibGUgbXVzdCBiZSBhIG1hdHJpeCB3aXRoIHJvd3MgYmVpbmcgdGF4YSBhbmQgY29sdW1ucyBiZWluZyByYW5rcy4KMy4gVGhlIHNhbXBsZSBkYXRhIG11c3QgYmUgZGF0YSBmcmFtZSB3aXRoIHJvd3MgYmVpbmcgc2FtcGxlcy4KClRvIGRvdWJsZSBjaGVjayBpZiBldmVyeXRoaW5nIHdvcmtzIGxldCdzIGRvIHNvbWUgdmFsaWRpdHkgY2hlY2tzOgoKYGBge3J9CnN0b3BpZm5vdChhbGwocm93bmFtZXMob3R1cykgJWluJSByb3duYW1lcyhzZGF0YSkpKQpzdG9waWZub3QobnJvdyhvdHVzKSA9PSBucm93KHNkYXRhKSkKcHJpbnQoInNhbXBsZSBuYW1lcyBtYXRjaCIpCgpzdG9waWZub3QoYWxsKGNvbG5hbWVzKG90dXMpICVpbiUgcm93bmFtZXModGF4X21hdHJpeCkpKQpzdG9waWZub3QobmNvbChvdHVzKSA9PSBucm93KHRheF9tYXRyaXgpKQpzdG9waWZub3QoIWFueUR1cGxpY2F0ZWQodGF4X21hdHJpeCkpCnByaW50KCJ0YXhhIGxvb2sgb2theSIpCgpzdG9waWZub3QoIWFueUR1cGxpY2F0ZWQoc2RhdGEpKQpwcmludCgic2FtcGxlIGRhdGEgbG9va3Mgb2theSIpCmBgYAoKSWYgdGhhdCBwYXNzZXMgd2UgY2FuIGdvIGFoZWFkIGFuZCBidWlsZCBvdXIgcGh5bG9zZXEgb2JqZWN0LgoKYGBge3J9CnBzIDwtIHBoeWxvc2VxKAogIG90dV90YWJsZShvdHVzLCB0YXhhX2FyZV9yb3dzID0gRkFMU0UpLAogIHRheF90YWJsZSh0YXhfbWF0cml4KSwKICBzYW1wbGVfZGF0YShzZGF0YSkKKQoKcHMKYGBgCgpgYGB7cn0KbmFtZXMoc2FtcGxlX2RhdGEocHMpKQpib3dlbCA8LSBzYW1wbGVfZGF0YShwcykkYm93ZWwKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpgYGAKCmBgYHtyfQojRGlmZmVyZW50aWFsIFRlc3QKI1VuY29tbWVudCB0aGlzIGNvZGUgY2h1bmsgdG8gcnVuIHRoZSBDT1JOQ09CIG1vZGVsaW5nLgojT3RoZXJ3aXNlLCBsb2FkIHRoZSBkdl9hbmFseXNpcyBvYmplY3QgYWxyZWFkeSBzYXZlZCBmcm9tIGEgcHJldmlvdXNseSBjb21wbGV0ZWQgbW9kZWxpbmcgcnVuLgojZHZfYW5hbHlzaXMgPC0gZGlmZmVyZW50aWFsVGVzdChmb3JtdWxhID0gfiBib3dlbCArIHNleCArIGFnZSArIEJNSV9DQUxDICsgdmVuZG9yX2Rhc2hib2FyZCArIGVHRlIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaGkuZm9ybXVsYSA9IH4gMSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm11bGFfbnVsbCA9IH4gc2V4ICsgYWdlICsgQk1JX0NBTEMgKyB2ZW5kb3JfZGFzaGJvYXJkICsgZUdGUiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBoaS5mb3JtdWxhX251bGwgPSB+IDEsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gcHMsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gIkxSVCIsIGJvb3QgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bGxfb3V0cHV0ID0gVFJVRSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZkcl9jdXRvZmYgPSAwLjA1KQoKI3NhdmVSRFMoZHZfYW5hbHlzaXMsICJjb3JuY29iLnJkcyIpCmBgYAoKCmBgYHtyfQojTG9hZCBhIHByZXZpb3VzIENPUk5DT0IgbW9kZWxpbmcKI0NsaWNrIG9uIHRoZSAiY29ybmNvYi5yZHMiIGZpbGUgaW4gdGhlIGZvbGRlciB3aXRoIFIgU3R1ZGlvIG9wZW4gYW5kIGFkZCB0aGUgZGF0YWZyYW1lIHRvIHRoZSBlbnZpcm9ubWVudC4gTmFtZSBpdCAiY29ybmNvYiI6CmR2X2FuYWx5c2lzIDwtIGNvcm5jb2IKI1NlZSB0aGUgc2lnbmlmaWNhbnQgdGF4YSBmcm9tIHRoZSBjb21wdXRhdGlvbjoKZHZfYW5hbHlzaXMkc2lnbmlmaWNhbnRfdGF4YQpgYGAKCgoKYGBge3J9CiNwcmVwYXJlIHRoZSB0YXhhIGRmIHdpdGggRkRSIHAgdmFsdWVzIGZvciBtYW5pcHVsYXRpb246CnRheGE8LWR2X2FuYWx5c2lzJGFsbF9tb2RlbHMKZHZfYW5hbHlzaXMkc2lnbmlmaWNhbnRfdGF4YQphcy5kYXRhLmZyYW1lKGR2X2FuYWx5c2lzJHBfZmRyKQp0YXhhX3AgPC0gRHJvcE5BKGFzLmRhdGEuZnJhbWUoZHZfYW5hbHlzaXMkcF9mZHIpLCBWYXIgPSAiZHZfYW5hbHlzaXMkcF9mZHIiKQp0YXhhX3BbMV0KdGF4YVtbMV1dJGNvZWZmaWNpZW50cwpgYGAKCgpgYGB7cn0KI0xvYWQgdGhlIGFyaXZhbGVfcGh5bG8ucmRzIGZpbGUgaW4gdGhlIHByb2plY3QgZm9sZGVyIGFuZCBsb2FkIHRoZSBvYmplY3QgaW50byB0aGUgZW52aXJvbm1lbnQuCgojUmFyZWZ5IHRoZSBnZW5vdGVrIGRhdGFzZXQgdG8gYW4gZXZlbiBkZXB0aCB1c2luZyBwaHlsb3NlcS4Kc2FtcGxlX2RhdGEoYXJpdmFsZV9waHlsbykgCiNUb20gV2lsbWFuc2tpLCBQaEQncyBjb2RlOgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnJhcmVmaWVkX2dlbm90ZWs9cmFyZWZ5X2V2ZW5fZGVwdGgoYXJpdmFsZV9waHlsbywgc2FtcGxlLnNpemUgPSBtaW4oc2FtcGxlX3N1bXMoYXJpdmFsZV9waHlsbykpLAogIHJuZ3NlZWQgPSAxMTEsIHJlcGxhY2UgPSBGQUxTRSwgdHJpbU9UVXMgPSBUUlVFLCB2ZXJib3NlID0gVFJVRSkKCnJpY2huZXNzIDwtIGVzdGltYXRlX3JpY2huZXNzKHJhcmVmaWVkX2dlbm90ZWssIG1lYXN1cmVzPWMoIlNoYW5ub24iLCJPYnNlcnZlZCIpKQoKc2F2ZVJEUyhyaWNobmVzcywgInJpY2huZXNzLnJkcyIpCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKYGBgCgoKYGBge3J9CiNnZXQgUGllbG91J3MgRXZlbm5lc3MKcmljaG5lc3MkcHVibGljX2NsaWVudF9pZCA8LXNhbXBsZV9kYXRhKHJhcmVmaWVkX2dlbm90ZWspJHB1YmxpY19jbGllbnRfaWQKbGlicmFyeShidG9vbHMpCnJpY2huZXNzJFBpZWxvdSA8LSByaWNobmVzcyRTaGFubm9uL3JpY2huZXNzJE9ic2VydmVkCgpyaWNobmVzcwpgYGAKCgpgYGB7cn0KI0NoZWNrIGRpc3RyaWJ1dGlvbiBvZiBkYXRhOgpoaXN0KHJpY2huZXNzJFBpZWxvdSwKICAgICBtYWluID0gIlBpZWxvdSdzIEV2ZW5uZXNzIChTaGFubm9uL09ic2VydmVkIEFTVikiLAogICAgIHhsYWIgPSAiRXZlbm5lc3MiLAogICAgIHhsaW0gPSBjKDAsMC4wNSksCiAgICAgYnJlYWtzID0gMjAwKQoKaGlzdChyaWNobmVzcyRTaGFubm9uLAogICAgIG1haW4gPSAiU2hhbm5vbiBEaXZlcnNpdHkiLAogICAgIHhsYWIgPSAiRGl2ZXJzaXR5IEluZGV4IiwKICAgICB4bGltID0gYygwLDYpLAogICAgIGJyZWFrcyA9IDIwKQoKaGlzdChyaWNobmVzcyRPYnNlcnZlZCwKICAgICBtYWluID0gIk9ic2VydmVkIEFTVnMiLAogICAgIHhsYWIgPSAiQVNWcyIsCiAgICAgeGxpbSA9IGMoMCwxMDAwKSwKICAgICBicmVha3MgPSAzMCkKYGBgCgpgYGB7cn0KY29tYmluYXRpb25zIDwtIGxpc3QoYygiQ29uc3RpcGF0aW9uIiwiTG93IE5vcm1hbCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJDb25zdGlwYXRpb24iLCJIaWdoIE5vcm1hbCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJDb25zdGlwYXRpb24iLCJEaWFycmhlYSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJMb3cgTm9ybWFsIiwiSGlnaCBOb3JtYWwiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiTG93IE5vcm1hbCIsIkRpYXJyaGVhIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIkhpZ2ggTm9ybWFsIiwiRGlhcnJoZWEiKSkKZGF0JGJvd2VsIDwtIGZhY3RvcihkYXQkYm93ZWwsIGxldmVscyA9IGMoIkNvbnN0aXBhdGlvbiIsICJMb3cgTm9ybWFsIiwgIkhpZ2ggTm9ybWFsIiwgIkRpYXJyaGVhIiksIGxhYmVscyA9IGMoIkNvbnN0aXBhdGlvbiIsICJMb3cgTm9ybWFsIiwgIkhpZ2ggTm9ybWFsIiwgIkRpYXJyaGVhIikpCmBgYAoKCmBgYHtyfQojQmVnaW4gcHJlcGFyaW5nIGd1dCBtaWNyb2Jpb21lIGRhdGEgcmVzdWx0cyBmb3IgcGxvdHRpbmcKI0ltcG9ydCBndXQgZGYgZm9yIHByZXByb2Nlc3Npbmc6CgpkZiA8LSByZWFkLmNzdigiZ3V0X2Z1bGwuY3N2IiwgY2hlY2submFtZXM9RikKY29sbmFtZXMoZGYpID0gZ3N1YigibmFuIiwgIlVuY2xhc3NpZmllZCIsIGNvbG5hbWVzKGRmKSkKY29tcGFyaXNvbnMgPSBsaXN0KGMoIkNvbnN0aXBhdGlvbiIsIkhpZ2ggTm9ybWFsIiksYygiTG93IE5vcm1hbCIsIkhpZ2ggTm9ybWFsIiksYygiRGlhcnJoZWEiLCJIaWdoIE5vcm1hbCIpKQpkZiRib3dlbCA8LSBmYWN0b3IoZGYkYm93ZWwsIGxldmVscyA9IGMoMSwyLDMsNCksIGxhYmVscyA9IGMoIkNvbnN0aXBhdGlvbiIsICJMb3cgTm9ybWFsIiwgIkhpZ2ggTm9ybWFsIiwgIkRpYXJyaGVhIikpCmRmX290dXMgPC0gZHBseXI6OnNlbGVjdChkZiwgLWMoInB1YmxpY19jbGllbnRfaWQiLCJib3dlbCIsInZlbmRvcl9kYXNoYm9hcmQiLCJzZXgiLCJhZ2UiLCJCTUlfQ0FMQyIsImVHRlIiKSkKCmRmX290dXMgPC0gYXMuZGF0YS5mcmFtZShjbHIoYXMubWF0cml4KGRmX290dXMpKSkKZGZfc2VsZWN0IDwtIGRwbHlyOjpzZWxlY3QoZGYsIGMoMTo3KSkKZGZfb3R1cyA8LSBjYmluZChkZl9zZWxlY3QsZGZfb3R1cykKZGYgPC0gZGZfb3R1cwpkYXQgPC0gZGZfb3R1cwoKIyBDcmVhdGUgdGhlIGRmcyB0byBzdG9yZSBCTUYgbWV0YWRhdGEgYW5kIHAgdmFsdWVzIGZvciBlYWNoIGhpdApjb25zdCA8LSBjKCkKY29uc3RfcCA8LSBjKCkKbG93IDwtIGMoKQpsb3dfcCA8LSBjKCkKZGlhcnJoZWEgPC0gYygpCmRpYXJyaGVhX3AgPC0gYygpCnRheGFfbmFtZXMgPC0gYygpCmZhbWlseV9uYW1lcyA8LSBjKCkKZ2VudXNfbmFtZXMgPC0gYygpCmxpa2VsaWhvb2QgPC0gYygpCmFkal9wIDwtIGMoKQpuYW1lcyhkdl9hbmFseXNpcyRwKSA9IGdzdWIoIm5hbiIsICJVbmNsYXNzaWZpZWQiLCBuYW1lcyhkdl9hbmFseXNpcyRwKSkKCiNBZGQgYWxsIHRoZSBwIHZhbHVlcyBhbmQgbWV0YWRhdGEgdG8gdGhlIHJpZ2h0IGRmczoKZm9yIChpIGluIDE6bGVuZ3RoKGR2X2FuYWx5c2lzJGFsbF9tb2RlbHNbbmFtZXMoZHZfYW5hbHlzaXMkcCldKSkgewogIGNvbnN0X3BbaV0gPC0gZHZfYW5hbHlzaXMkYWxsX21vZGVsc1tbaV1dJGNvZWZmaWNpZW50c1syLDRdCiAgY29uc3RbaV0gPC0gZHZfYW5hbHlzaXMkYWxsX21vZGVsc1tbaV1dJGNvZWZmaWNpZW50c1syLDFdCiAgbG93X3BbaV0gPC0gZHZfYW5hbHlzaXMkYWxsX21vZGVsc1tbaV1dJGNvZWZmaWNpZW50c1szLDRdCiAgbG93W2ldIDwtIGR2X2FuYWx5c2lzJGFsbF9tb2RlbHNbW2ldXSRjb2VmZmljaWVudHNbMywxXQogIGRpYXJyaGVhX3BbaV0gPC0gZHZfYW5hbHlzaXMkYWxsX21vZGVsc1tbaV1dJGNvZWZmaWNpZW50c1s0LDRdCiAgZGlhcnJoZWFbaV0gPC0gZHZfYW5hbHlzaXMkYWxsX21vZGVsc1tbaV1dJGNvZWZmaWNpZW50c1s0LDFdCiAgdGF4YV9uYW1lc1tpXSA8LSBuYW1lcyhkdl9hbmFseXNpcyRwKVtpXQogIGZhbWlseV9uYW1lc1tpXSA8LSBzdHJzcGxpdCh0YXhhX25hbWVzW2ldLCcuJyxmaXhlZD1UUlVFKVtbMV1dWzVdCiAgZ2VudXNfbmFtZXNbaV0gPC0gc3Ryc3BsaXQodGF4YV9uYW1lc1tpXSwnLicsZml4ZWQ9VFJVRSlbWzFdXVs2XQogIGxpa2VsaWhvb2RbaV0gPC0gZHZfYW5hbHlzaXMkYWxsX21vZGVsc1tbaV1dJGxvZ0wKICBhZGpfcFtpXSA8LSBkdl9hbmFseXNpcyRwX2ZkcltbaV1dCn0KZ2VudXNfbmFtZXNbaV0gPC0gc3Ryc3BsaXQodGF4YV9uYW1lc1tpXSwnLicsZml4ZWQ9VFJVRSlbWzFdXVs2XQoKI0NyZWF0ZSBmaW5hbCBwLXZhbHVlIGRmOgpwX2RmIDwtIGJpbmRfY29scyh0YXhhX25hbWVzLGZhbWlseV9uYW1lcyxnZW51c19uYW1lcywgbGlrZWxpaG9vZCwgYWRqX3AsIGNvbnN0LGNvbnN0X3AsbG93LGxvd19wLGRpYXJyaGVhLGRpYXJyaGVhX3ApCm5hbWVzKHBfZGYpIDwtIGMoIkdlbmVyYSIsIkZhbWlseSIsIkdlbnVzIiwiTG9nTCIsIkFkai5QIiwiQ29uc3QuQmV0YSIsIkNvbnN0LlAuVmFsIiwiTG93LkJldGEiLCJMb3cuUC5WYWwiLCJEaWFycmhlYS5CZXRhIiwiRGlhcnJoZWEuUC5WYWwiKQpwX2RmJENvbWJpbmVkIDwtIHBhc3RlKHBfZGYkRmFtaWx5LHBfZGYkR2VudXMpCmFiIDwtIGNvbFN1bXMoZGZfb3R1c1tuYW1lcyhkZl9vdHVzKSAlaW4lIHBhc3RlKCJ0YXhhXyIsbmFtZXMoZHZfYW5hbHlzaXMkcCksc2VwPSIiKV0pL2NvbFN1bXMoISFkZl9vdHVzW25hbWVzKGRmX290dXMpICVpbiUgcGFzdGUoInRheGFfIixuYW1lcyhkdl9hbmFseXNpcyRwKSxzZXA9IiIpXSkKcF9kZiRNZWFuLkFidW5kYW5jZSA8LSBhYltwYXN0ZSgidGF4YV8iLHBfZGYkR2VuZXJhLHNlcD0iIildCnBfZGYkQ29uc3QuQWRqLlAuVmFsIDwtIHAuYWRqdXN0KGNvbnN0X3AsIG1ldGhvZCA9ICJmZHIiLCBuID0gbGVuZ3RoKGNvbnN0X3ApKQpwX2RmJExvdy5BZGouUC5WYWwgPC0gcC5hZGp1c3QobG93X3AsIG1ldGhvZCA9ICJmZHIiLCBuID0gbGVuZ3RoKGxvd19wKSkKcF9kZiREaWFycmhlYS5BZGouUC5WYWwgPC0gcC5hZGp1c3QoZGlhcnJoZWFfcCwgbWV0aG9kID0gImZkciIsIG4gPSBsZW5ndGgoZGlhcnJoZWFfcCkpCnBfZGYgPC0gcF9kZltvcmRlcigtcF9kZiRNZWFuLkFidW5kYW5jZSksXQpzZXQgPC0gc3Vic2V0KHBfZGZbd2hpY2gocF9kZiRBZGouUCA8IDAuMDUpLF0sIEdlbnVzICE9ICdVbmNsYXNzaWZpZWQnKQpzZXQgPC0gc3Vic2V0KHNldFtvcmRlcigtc2V0JE1lYW4uQWJ1bmRhbmNlKSxdLCBHZW51cyAhPSAnVW5jbGFzc2lmaWVkJykKYWJ1bmRhbnRfbGlzdCA8LSBsaXN0KCkKYWJ1bmRhbnRfZ2VudXMgPC0gbGlzdCgpCmFidW5kYW50IDwtIHBhc3RlKCJ0YXhhXyIsc2V0W29yZGVyKC1zZXQkTWVhbi5BYnVuZGFuY2UpLF0kR2VuZXJhLHNlcD0iIikKZm9yIChpIGluIDE6NjgpIHsKICBhYnVuZGFudF9saXN0W2ldIDwtIHBhc3RlKHN0cnNwbGl0KGFidW5kYW50W2ldLCcuJyxmaXhlZD1UUlVFKVtbMV1dWzVdLHN0cnNwbGl0KGFidW5kYW50W2ldLCcuJyxmaXhlZD1UUlVFKVtbMV1dWzZdKQogIGFidW5kYW50X2dlbnVzW2ldIDwtIHBhc3RlKHN0cnNwbGl0KGFidW5kYW50W2ldLCcuJyxmaXhlZD1UUlVFKVtbMV1dWzZdKQp9CgojdG9wIDEwIG1vc3QgYWJ1bmRhbnQgbm9uLXVuY2xhc3NpZmllZCBoaXRzCmFidW5kYW50X3RydW5jIDwtIHNldFttYXRjaChhYnVuZGFudF9saXN0WyFpcy5uYShzZXQkQ29tYmluZWRbbWF0Y2goYWJ1bmRhbnRfbGlzdCxzZXQkQ29tYmluZWQpXSldLHNldCRDb21iaW5lZCksXVt3aGljaChzZXQkQWRqLlA8MC4wNSksXSRDb21iaW5lZFsxOjEwXQpgJSFpbiVgIDwtIE5lZ2F0ZShgJWluJWApCnQgPC0gc2V0W3NldCRDb21iaW5lZCAlIWluJSBhYnVuZGFudF90cnVuYyxdCgojY3JlYXRlIHRoZSBzZXQgb2YgaGl0cyB0aGF0IGFyZSB0b3AgMTAgbW9zdCBhYnVuZGFudCwgQWtrZXJtYW5zaWEsIGFuZCB0b3AgOSBtb3N0IHNpZ25pZmljYW50ID0gMjAgaGl0czoKc3BhbiA8LSByYmluZChzZXRbb3JkZXIoc2V0Wy1vcmRlcihzZXRbIXNldCRDb21iaW5lZCAlaW4lIGFidW5kYW50X3RydW5jLF0kQWRqLlApLF1bd2hpY2goc2V0JEFkai5QPDAuMDUpLF0kTWVhbi5BYnVuZGFuY2UgJSFpbiUgYWJ1bmRhbnRfdHJ1bmMpLF1bMToxMCxdLAp0W21hdGNoKCdBa2tlcm1hbnNpYWNlYWUgQWtrZXJtYW5zaWEnLHQkQ29tYmluZWQpLF0sCnRbb3JkZXIodCRDb25zdC5BZGouUC5WYWwpLF1bMTo5LF0pCnNwYW4kTGV0dGVycyA8LSBMRVRURVJTWzE6MjBdCnBfZGYkTGV0dGVycyA8LSBjKE5BKQp0ZXN0IDwtIHJiaW5kKHNwYW4scF9kZltwX2RmJENvbWJpbmVkICUhaW4lIHNwYW4kQ29tYmluZWQsXSkKdGVzdCA8LSB0ZXN0WyFkdXBsaWNhdGVkKHRlc3QkR2VuZXJhKSxdCnBfZGYgPC0gdGVzdApwX2RmIDwtIHBfZGZbb3JkZXIocF9kZiRBZGouUCksXQpwX2RmIDwtIHBfZGZbb3JkZXIoLXBfZGYkTWVhbi5BYnVuZGFuY2UpLF0KYGBgCgoKYGBge3J9CiNQaWVsb3UncyBFdmVubmVzczoKbW9kZWwgPSB5IH4geApkZl9udW0gPC0gbWVyZ2UocmljaG5lc3MsIGRmX290dXMsIGJ5PSJwdWJsaWNfY2xpZW50X2lkIikKZGZfbnVtJGJvd2VsIDwtIGZhY3RvcihkZl9udW0kYm93ZWwsIG9yZGVyID0gVFJVRSkKZDFfcGxvdCA8LSBsbShQaWVsb3UgfiBib3dlbCwgZGF0YSA9IGRmX251bSkKcHZhbDEgPSBzdW1tYXJ5KGQxX3Bsb3QpJGNvZWZmaWNpZW50c1syLDRdCnIxID0gc3VtbWFyeShkMV9wbG90KSRhZGouci5zcXVhcmVkCnB2YWwxCnIxCgpkMSA8LSBnZ3Bsb3QoZGF0YSA9IGRmX251bSwgYWVzKHggPSBmYWN0b3IoYm93ZWwsIGxldmVsID0gYygiQ29uc3RpcGF0aW9uIiwgIkxvdyBOb3JtYWwiLCAiSGlnaCBOb3JtYWwiLCAiRGlhcnJoZWEiKSwgbGFiZWxzID0gYygiQ29uc3RpcGF0aW9uIiwgIkxvdyBOb3JtYWwiLCAiSGlnaCBOb3JtYWwiLCAiRGlhcnJoZWEiKSksIHkgPSBQaWVsb3UsIGdyb3VwID0gZmFjdG9yKGJvd2VsKSkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGJxdW90ZShhdG9wKH5pdGFsaWMoImFkaiBSIileMn4iID0gIn4uKGZvcm1hdEMoYXMubnVtZXJpYyhyMSksMykpLH5pdGFsaWMoIlAgdmFsdWUiKX4iID0gIn4uKGZvcm1hdEMoYXMubnVtZXJpYyhwdmFsMSksMykpKSkpKwogIGdlb21fYmVlc3dhcm0oYWVzKGNvbG9yID0gYm93ZWwpLCBjZXggPSAwLjUpICsKICBnZW9tX2JveHBsb3QoYWxwaGE9MCkgKwogIHlsaW0oMC4wMDUsMC4wNSkrCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9IHkgfiB4LCBhZXMoZ3JvdXAgPSAxKSkgKwogIGdndGl0bGUobGFiZWwgPSAiQylcblBpZWxvdSdzIEV2ZW5uZXNzIHZzIEJNRiIpICsKICB4bGFiKCJCb3dlbCBNb3ZlbWVudCBGcmVxdWVuY3kgKEJNRikiKSArCiAgeWxhYigiUGllbG91J3MgRXZlbm5lc3MiKSArCiAgc2NhbGVfY29sb3VyX2Rpc2NyZXRlKG5hbWU9IkJNRiBDYXRlZ29yeSIsIGxpbWl0cyA9IGMoIkNvbnN0aXBhdGlvbiIsICJMb3cgTm9ybWFsIiwgIkhpZ2ggTm9ybWFsIiwgIkRpYXJyaGVhIiksIGxhYmVscz1jKCJDb25zdGlwYXRpb24iLCAiTG93IE5vcm1hbCIsICJIaWdoIE5vcm1hbCIsICJEaWFycmhlYSIpKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NykpKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKZDEKCiNTaGFubm9uIERpdmVyc2l0eToKbW9kZWwgPSB5IH4geApkMl9wbG90IDwtIGxtKFNoYW5ub24gfiBib3dlbCwgZGF0YSA9IGRmX251bSkKcHZhbDIgPSBzdW1tYXJ5KGQyX3Bsb3QpJGNvZWZmaWNpZW50c1syLDRdCnIyID0gc3VtbWFyeShkMl9wbG90KSRhZGouci5zcXVhcmVkCnB2YWwyCnIyCgpkMiA8LSBnZ3Bsb3QoZGF0YSA9IGRmX251bSwgYWVzKHggPSBmYWN0b3IoYm93ZWwsIGxldmVsID0gYygiQ29uc3RpcGF0aW9uIiwgIkxvdyBOb3JtYWwiLCAiSGlnaCBOb3JtYWwiLCAiRGlhcnJoZWEiKSwgbGFiZWxzID0gYygiQ29uc3RpcGF0aW9uIiwgIkxvdyBOb3JtYWwiLCAiSGlnaCBOb3JtYWwiLCAiRGlhcnJoZWEiKSksIHkgPSBTaGFubm9uLCBncm91cCA9IGJvd2VsKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoYnF1b3RlKGF0b3Aofml0YWxpYygiYWRqIFIiKV4yfiIgPSAifi4oZm9ybWF0Qyhhcy5udW1lcmljKHIyKSwzKSksfml0YWxpYygiUCB2YWx1ZSIpfiIgPSAifi4oZm9ybWF0Qyhhcy5udW1lcmljKHB2YWwyKSwzKSkpKSkrCiAgZ2VvbV9iZWVzd2FybShhZXMoY29sb3IgPSBmYWN0b3IoYm93ZWwpKSwgY2V4ID0gMC41KSArCiAgZ2VvbV9ib3hwbG90KGFscGhhPTApICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geSB+IHgsIGFlcyhncm91cCA9IDEpKSArCiAgZ2d0aXRsZShsYWJlbCA9ICJCKVxuU2hhbm5vbiBEaXZlcnNpdHkgdnMgQk1GIikgKwogIHhsYWIoIkJvd2VsIE1vdmVtZW50IEZyZXF1ZW5jeSAoQk1GKSIpICsKICB5bGFiKCJTaGFubm9uIERpdmVyc2l0eSIpICsKICBzY2FsZV9jb2xvdXJfZGlzY3JldGUobmFtZT0iQk1GIENhdGVnb3J5IiwgbGltaXRzID0gYygiQ29uc3RpcGF0aW9uIiwgIkxvdyBOb3JtYWwiLCAiSGlnaCBOb3JtYWwiLCAiRGlhcnJoZWEiKSwgbGFiZWxzPWMoIkNvbnN0aXBhdGlvbiIsICJMb3cgTm9ybWFsIiwgIkhpZ2ggTm9ybWFsIiwgIkRpYXJyaGVhIikpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT03KSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTApLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQpkMgoKI09ic2VydmVkIEFTVnM6Cm1vZGVsID0geSB+IHgKZDNfcGxvdCA8LSBsbShPYnNlcnZlZCB+IGJvd2VsLCBkYXRhID0gZGZfbnVtKQpwdmFsMyA9IHN1bW1hcnkoZDNfcGxvdCkkY29lZmZpY2llbnRzWzIsNF0KcjMgPSBzdW1tYXJ5KGQzX3Bsb3QpJGFkai5yLnNxdWFyZWQKcHZhbDMKcjMKCmQzIDwtIGdncGxvdChkYXRhID0gZGZfbnVtLCBhZXMoeCA9IGZhY3Rvcihib3dlbCwgbGV2ZWwgPSBjKCJDb25zdGlwYXRpb24iLCAiTG93IE5vcm1hbCIsICJIaWdoIE5vcm1hbCIsICJEaWFycmhlYSIpLCBsYWJlbHMgPSBjKCJDb25zdGlwYXRpb24iLCAiTG93IE5vcm1hbCIsICJIaWdoIE5vcm1hbCIsICJEaWFycmhlYSIpKSwgeSA9IE9ic2VydmVkLCBncm91cCA9IGJvd2VsKSkrCiAgc2NhbGVfeF9kaXNjcmV0ZShicXVvdGUoYXRvcCh+aXRhbGljKCJhZGogUiIpXjJ+IiA9ICJ+Lihmb3JtYXRDKGFzLm51bWVyaWMocjMpLDMpKSx+aXRhbGljKCJQIHZhbHVlIil+IiA9ICJ+Lihmb3JtYXRDKGFzLm51bWVyaWMocHZhbDMpLDMpKSkpKSsKICBnZW9tX2JlZXN3YXJtKGFlcyhjb2xvciA9IGZhY3Rvcihib3dlbCkpLCBjZXggPSAwLjUpICsKICBnZW9tX2JveHBsb3QoYWxwaGE9MCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgYWVzKGdyb3VwID0gMSkpICsKICBnZ3RpdGxlKGxhYmVsID0gIkEpXG5PYnNlcnZlZCBBU1ZzIHZzIEJNRiIpICsKICB4bGFiKCJCb3dlbCBNb3ZlbWVudCBGcmVxdWVuY3kgKEJNRikiKSArCiAgeWxhYigiT2JzZXJ2ZWQgQVNWcyIpICsKICBzY2FsZV9jb2xvdXJfZGlzY3JldGUobmFtZT0iQk1GIENhdGVnb3J5IiwgbGltaXRzID0gYygiQ29uc3RpcGF0aW9uIiwgIkxvdyBOb3JtYWwiLCAiSGlnaCBOb3JtYWwiLCAiRGlhcnJoZWEiKSwgbGFiZWxzPWMoIkNvbnN0aXBhdGlvbiIsICJMb3cgTm9ybWFsIiwgIkhpZ2ggTm9ybWFsIiwgIkRpYXJyaGVhIikpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT03KSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTApLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQpkMwoKUFNPIDwtIGdnYXJyYW5nZShkMywgZDIsIGQxLCBsZWdlbmQgPSAidG9wIiwgYWxpZ24gPSAiaHYiLCBjb21tb24ubGVnZW5kID0gVFJVRSwgd2lkdGhzID0gYyg3LDcsNyksIGhlaWdodHMgPSBjKDIwLDIwLDIwKSwgbnJvdyA9IDEsIG5jb2wgPSAzKSsgdGhlbWUocGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwwLDAsMCkpClBTTwpnZ3NhdmUoCiAgIlBTT3ZCTUYucG5nIiwKICBwbG90ID0gUFNPLAogIGRldmljZSA9IE5VTEwsCiAgcGF0aCA9IE5VTEwsCiAgc2NhbGUgPSAxLAogIHdpZHRoID0gTkEsCiAgaGVpZ2h0ID0gTkEsCiAgdW5pdHMgPSBjKCJpbiIsICJjbSIsICJtbSIsICJweCIpLAogIGRwaSA9IDMwMCwKICBsaW1pdHNpemUgPSBUUlVFLAogIGJnID0gTlVMTAopCmBgYAoKCgpgYGB7cn0KI0Fubm90YXRpb24gZnVuY3Rpb246CnNpZyA9IGZ1bmN0aW9uKHgpewogIGlmKHggPCAwLjAwMSl7IioqKiJ9IAogIGVsc2UgaWYoeCA8IDAuMDEpeyIqKiJ9CiAgZWxzZSBpZih4IDwgMC4wNSl7IioifQogIGVsc2V7TkF9fQoKI3VzZSBndXQgZGYgdG8gY29uc3RydWN0IGNvbHVtbi1zcGVjaWZpYyBkZiBmb3IgcGxvdHRpbmcgZnVuY3Rpb24KZGYgPC0gcmVhZC5jc3YoImd1dF9mdWxsLmNzdiIsIGNoZWNrLm5hbWVzPUYpCmNvbG5hbWVzKGRmKSA9IGdzdWIoIm5hbiIsICJVbmNsYXNzaWZpZWQiLCBjb2xuYW1lcyhkZikpCmNvbXBhcmlzb25zID0gbGlzdChjKCJDb25zdGlwYXRpb24iLCJIaWdoIE5vcm1hbCIpLGMoIkxvdyBOb3JtYWwiLCJIaWdoIE5vcm1hbCIpLGMoIkRpYXJyaGVhIiwiSGlnaCBOb3JtYWwiKSkKZGYkYm93ZWwgPC0gZmFjdG9yKGRmJGJvd2VsLCBsZXZlbHMgPSBjKDEsMiwzLDQpLCBsYWJlbHMgPSBjKCJDb25zdGlwYXRpb24iLCAiTG93IE5vcm1hbCIsICJIaWdoIE5vcm1hbCIsICJEaWFycmhlYSIpKQpkZl9vdHVzIDwtIGRwbHlyOjpzZWxlY3QoZGYsIC1jKCJwdWJsaWNfY2xpZW50X2lkIiwiYm93ZWwiLCJ2ZW5kb3JfZGFzaGJvYXJkIiwic2V4IiwiYWdlIiwiQk1JX0NBTEMiLCJlR0ZSIikpCgojcmVmcmVzaCBkYXRhZnJhbWVzOgpkZl9vdHVzIDwtIGFzLmRhdGEuZnJhbWUoY2xyKGFzLm1hdHJpeChkZl9vdHVzKSkpCmRmX3NlbGVjdCA8LSBkcGx5cjo6c2VsZWN0KGRmLCBjKDE6NykpCmRmX290dXMgPC0gY2JpbmQoZGZfc2VsZWN0LGRmX290dXMpCmRmIDwtIGRmX290dXMKZGF0IDwtIGRmX290dXMKCiNJbml0aWFsaXplIHZlY3RvcnM6CmRmJHAudmFsdWUgPC0gTkEKZGYkcHZhbCA8LSBOVUxMCmRmJHAudmFsIDwtIE5VTEwKY291bnRlciA8PC0gMQoKI1Bsb3R0aW5nOgoKIyBTcGVjaWFsIEdyYXBoaW5nIEZ1bmN0aW9uOgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnRlc3QgPSBmdW5jdGlvbih4LHkseixqKSB7CiAgd29yayA8LSBOVUxMCiAgcmVzdWx0cyA8LSBOVUxMCiAgeCA9IE5VTEwKICB5ID0gTlVMTAogIGlmIChjb3VudGVyID09IDEpIHt6ID0gY29tcGFyaXNvbnNbWzFdXVsxXX0KICBlbHNlIGlmIChjb3VudGVyID09IDIpIHt6ID0gY29tcGFyaXNvbnNbWzJdXVsxXX0KICBlbHNlIGlmIChjb3VudGVyID4gMikge3ogPSBjb21wYXJpc29uc1tbM11dWzFdfQogIHRlbXAgPC0gZGF0YS5mcmFtZSgibmFtZSIgPSBOQSwgInAudmFsdWUiID0gTkEsICJib3dlbCIgPSBOQSkKICBmb3IgKGkgaW4gMToyMCkgewogICAgdGVtcCRuYW1lIDwtIHBhc3RlKCJnZW51c18iLHNwYW4kR2VuZXJhW1tpXV0sc2VwPSIiKQogICAgdGVtcCRwLnZhbHVlIDwtIHNwYW4kQ29uc3QuQWRqLlAuVmFsW1tpXV0gCiAgICB0ZW1wJGJvd2VsIDwtICJDb25zdGlwYXRpb24iCiAgICB3b3JrIDwtIHJiaW5kKHdvcmssdGVtcCkKICAgIHRlbXAkcC52YWx1ZSA8LSBzcGFuJExvdy5BZGouUC5WYWxbW2ldXSAKICAgIHRlbXAkYm93ZWwgPC0gIkxvdyBOb3JtYWwiCiAgICB3b3JrIDwtIHJiaW5kKHdvcmssdGVtcCkKICAgIHRlbXAkcC52YWx1ZSA8LSBzcGFuJERpYXJyaGVhLkFkai5QLlZhbFtbaV1dIAogICAgdGVtcCRib3dlbCA8LSAiRGlhcnJoZWEiCiAgICB3b3JrIDwtIHJiaW5kKHdvcmssdGVtcCkKICB9CiAgaWYgKHpbWzFdXVsxXSA9PSBjb21wYXJpc29uc1tbMV1dWzFdKSB7cmVzdWx0cyA8LSBsaXN0KHAudmFsdWUgPSB3b3JrJHAudmFsdWVbMyooai0xKSsxXSl9CiAgZWxzZSBpZiAoeltbMV1dWzFdID09IGNvbXBhcmlzb25zW1syXV1bMV0pIHtyZXN1bHRzIDwtIGxpc3QocC52YWx1ZSA9IHdvcmskcC52YWx1ZVszKihqLTEpKzErMV0pIH0KICBlbHNlIGlmICh6W1sxXV1bMV0gPT0gY29tcGFyaXNvbnNbWzNdXVsxXSkge3Jlc3VsdHMgPC0gbGlzdChwLnZhbHVlID0gd29yayRwLnZhbHVlWzMqKGotMSkrMSsyXSl9CiAgY291bnRlcjw8LWNvdW50ZXIrMQogIGlmIChjb3VudGVyID4gMykge2NvdW50ZXI8PC0xfQogIHJldHVybihyZXN1bHRzKQp9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiNTdG9yZSBwbG90cyBpbiBsaXN0IG9mIHBsb3RzIGZvciBsb29waW5nIHRvIHBsb3QgbmV4dDoKbXlwbG90cyA8LSBsaXN0KCkgICMgbmV3IGVtcHR5IGxpc3QKZGZfdGVzdCA8LSBkZgpkZl90ZXN0W2RmX3Rlc3Q9PTBdIDwtIE5BCmZvciAoZ2VuZXJhIGluIDE6MjApIHsKICB5X25hbWUgPC0gcGFzdGUoInRheGFfIixzcGFuJEdlbmVyYVtnZW5lcmFdLHNlcD0iIikKICBteXBsb3RzW1tnZW5lcmFdXSA8LSBsb2NhbCh7CiAgICBwbG90bGltX2xvd2VyID0gbWluKApkZl90ZXN0WyFpcy5uYShkZl90ZXN0W3lfbmFtZV0pLF1beV9uYW1lXSkKICAgIHBsb3RsaW1fdXBwZXIgPSBtYXgoCmRmX3Rlc3RbIWlzLm5hKGRmX3Rlc3RbeV9uYW1lXSksXVt5X25hbWVdKQogICAgcGxvdGxpbV9iYXIgPSBwbG90bGltX2xvd2VyIC0gNAogICAgcGxvdGxpbV9tYXJnaW4gPSA2CiAgICBnZW5lcmEgPC0gZ2VuZXJhCiAgICBwbHQgPC0gZ2dwbG90KGRhdGEgPSBkZl90ZXN0LCBhZXMoeCA9IGJvd2VsLCB5ID0gLmRhdGFbW3lfbmFtZV1dLCBncm91cCA9IGJvd2VsKSkgKwogICAgc2NhbGVfeF9kaXNjcmV0ZShndWlkZSA9IGd1aWRlX2F4aXMobi5kb2RnZSA9IDIpKSsKICAgIGdlb21faml0dGVyKGFlcyhjb2xvciA9IGJvd2VsKSwgIHNpemUgPSAwLjEsIGNleCA9IDAuMDUpICsKICAgIGdlb21fYm94cGxvdChkYXRhID0gZGZfdGVzdCwgYWxwaGE9MC4wLG91dGxpZXIuc2hhcGUgPSBOQSkgKwogICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSkpICsKICAgIGdndGl0bGUobGFiZWwgPSBwYXN0ZShzcGFuJEZhbWlseVtnZW5lcmFdLCJcbiIsc3BhbiRHZW51c1tnZW5lcmFdLHNlcD0iIikpICsKICAgIGdlb21fc2lnbmlmKGRhdGEgPSBkZl90ZXN0LCBjb21wYXJpc29ucyA9IGNvbXBhcmlzb25zLCBtYXBfc2lnbmlmX2xldmVsID0gc2lnLCB0ZXN0ID0gJ3Rlc3QnLCB0ZXN0LmFyZ3MgPSBsaXN0KHogPSBjb21wYXJpc29ucywgaiA9IGdlbmVyYSksIHlfcG9zaXRpb24gPSBwbG90bGltX2JhcixzdGVwX2luY3JlYXNlID0gMC4xNSwgIHNpemUgPSAwLjUsIAogICAgICAgICAgICAgICAgdGV4dHNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICB0aXBfbGVuZ3RoID0gYygwLDApKSArCiAgICBjb29yZF9jYXJ0ZXNpYW4oeWxpbT1jKHBsb3RsaW1fbG93ZXIscGxvdGxpbV91cHBlciksY2xpcD0ib2ZmIikrCiAgICBsYWJzKGNvbG9yID0gIkJNRiBDYXRlZ29yeSIsIHkgPSBpZmVsc2UoKGdlbmVyYSA9PSAxIHwgZ2VuZXJhICA9PSA2IHwgZ2VuZXJhICA9PSAxMSB8IGdlbmVyYSA9PSAxNiksIkNMUiBBYnVuZGFuY2UiLCIiKSkgKwogICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NyksIHRpdGxlLnBvc2l0aW9uID0gJ2xlZnQnLCBucm93ID0gMSwgbmNvbCA9IDQpKSArCiAgICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLDAscGxvdGxpbV9tYXJnaW4sMCksICJjbSIpLCAKICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT01Ljc1KSwgCiAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksIAogICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwgCiAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTcpLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT03KSwgCiAgICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT03KSwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDAuOTUpCiAgfSkKfQoKCmBgYAoKCmBgYHtyfQojVHJ1bmNhdGUgdG8gdGhlIHRvcCAyMCBpbmNsdWRpbmcgQWtrZXJtYW5zaWEsIG1vc3QgYWJ1bmRhbnQsIGFuZCBtb3N0IHNpZ25pZmljYW50Ogp0aXRsZSA8LSBsaXN0KCkKZm9yKGkgaW4gc2VxKDE6MjApKSB7IHRpdGxlW2ldIDwtIG15cGxvdHNbW2MoaSldXSRsYWJlbHMkdGl0bGUgfQpwbG90czEgPC0gbXlwbG90c1t0aXRsZSAlaW4lIHBhc3RlKAogIHNwYW4kRmFtaWx5LAogICJcbiIsCiAgc3BhbiRHZW51cyxzZXA9IiIpXVsxOjIwXQpwbG90c19maW5hbCA8LSBwbG90czFbIXNhcHBseShwbG90czEsaXMubnVsbCldCgojQXJyYW5nZSB0aGUgcGxvdHM6CmZpbmFsMSA8LSBnZ2FycmFuZ2UocGxvdGxpc3QgPSBwbG90c19maW5hbFsxOjVdLCBsYWJlbHMgPSBMRVRURVJTWzE6NV0sIGxlZ2VuZCA9ICJ0b3AiLCBhbGlnbiA9ICJodiIsIGZvbnQubGFiZWwgPSBsaXN0KHNpemUgPSA4KSwgY29tbW9uLmxlZ2VuZCA9IFRSVUUsIG5yb3cgPSAxLCBuY29sID0gNSkgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLDAsMCwwKSwgImNtIikpCmZpbmFsMQpmaW5hbDIgPC0gZ2dhcnJhbmdlKHBsb3RsaXN0ID0gcGxvdHNfZmluYWxbNjoxMF0sIGxhYmVscyA9IExFVFRFUlNbNjoxMF0sIGxlZ2VuZCA9ICJ0b3AiLCBhbGlnbiA9ICJodiIsIGZvbnQubGFiZWwgPSBsaXN0KHNpemUgPSA4KSwgY29tbW9uLmxlZ2VuZCA9IFRSVUUsIG5yb3cgPSAxLCBuY29sID0gNSkgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLDAsMCwwKSwgImNtIikpCmZpbmFsMgoKZmluYWwzIDwtIGdnYXJyYW5nZShwbG90bGlzdCA9IHBsb3RzX2ZpbmFsWzExOjE1XSwgbGFiZWxzID0gTEVUVEVSU1sxMToxNV0sIGxlZ2VuZCA9ICJ0b3AiLCBhbGlnbiA9ICJodiIsIGZvbnQubGFiZWwgPSBsaXN0KHNpemUgPSA4KSwgY29tbW9uLmxlZ2VuZCA9IFRSVUUsIG5yb3cgPSAxLCBuY29sID0gNSkgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLDAsMCwwKSwgImNtIikpCmZpbmFsMwpmaW5hbDQgPC0gZ2dhcnJhbmdlKHBsb3RsaXN0ID0gcGxvdHNfZmluYWxbMTY6MjBdLCBsYWJlbHMgPSBMRVRURVJTWzE2OjIwXSwgbGVnZW5kID0gInRvcCIsIGFsaWduID0gImh2IiwgZm9udC5sYWJlbCA9IGxpc3Qoc2l6ZSA9IDgpLCBjb21tb24ubGVnZW5kID0gVFJVRSwgbnJvdyA9IDEsIG5jb2wgPSA1KSArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAsMCwwLDApLCAiY20iKSkKZmluYWw0CgpmaW5hbF9tYWluIDwtIGdnYXJyYW5nZShwbG90bGlzdCA9IHBsb3RzX2ZpbmFsWzE6MjBdLCBsYWJlbHMgPSBMRVRURVJTWzE6MjBdLCBsZWdlbmQgPSAidG9wIiwgYWxpZ24gPSAiaHYiLCBjb21tb24ubGVnZW5kID0gVFJVRSwgbnJvdyA9IDQsIG5jb2wgPSA1KQoKZ2dzYXZlKAogICJCTUZ2c0dlbmVyYTEucG5nIiwKICBwbG90ID0gZmluYWwxLAogIGRldmljZSA9IE5VTEwsCiAgcGF0aCA9IE5VTEwsCiAgc2NhbGUgPSAxLjUsCiAgd2lkdGggPSBOQSwKICBoZWlnaHQgPSBOQSwKICB1bml0cyA9IGMoImluIiwgImNtIiwgIm1tIiwgInB4IiksCiAgZHBpID0gMzAwLAogIGxpbWl0c2l6ZSA9IFRSVUUsCiAgYmcgPSBOVUxMCikKCmdnc2F2ZSgKICAiQk1GdnNHZW5lcmEyLnBuZyIsCiAgcGxvdCA9IGZpbmFsMiwKICBkZXZpY2UgPSBOVUxMLAogIHBhdGggPSBOVUxMLAogIHNjYWxlID0gMS41LAogIHdpZHRoID0gTkEsCiAgaGVpZ2h0ID0gTkEsCiAgdW5pdHMgPSBjKCJpbiIsICJjbSIsICJtbSIsICJweCIpLAogIGRwaSA9IDMwMCwKICBsaW1pdHNpemUgPSBUUlVFLAogIGJnID0gTlVMTAopCgpnZ3NhdmUoCiAgIkJNRnZzR2VuZXJhMy5wbmciLAogIHBsb3QgPSBmaW5hbDMsCiAgZGV2aWNlID0gTlVMTCwKICBwYXRoID0gTlVMTCwKICBzY2FsZSA9IDEuNSwKICB3aWR0aCA9IE5BLAogIGhlaWdodCA9IE5BLAogIHVuaXRzID0gYygiaW4iLCAiY20iLCAibW0iLCAicHgiKSwKICBkcGkgPSAzMDAsCiAgbGltaXRzaXplID0gVFJVRSwKICBiZyA9IE5VTEwKKQoKZ2dzYXZlKAogICJCTUZ2c0dlbmVyYTQucG5nIiwKICBwbG90ID0gZmluYWw0LAogIGRldmljZSA9IE5VTEwsCiAgcGF0aCA9IE5VTEwsCiAgc2NhbGUgPSAxLjUsCiAgd2lkdGggPSBOQSwKICBoZWlnaHQgPSBOQSwKICB1bml0cyA9IGMoImluIiwgImNtIiwgIm1tIiwgInB4IiksCiAgZHBpID0gMzAwLAogIGxpbWl0c2l6ZSA9IFRSVUUsCiAgYmcgPSBOVUxMCikKCgpgYGAKCgoK